#include "../s21_decimal.h"

int s21_max(int first, int second) { return first > second ? first : second; }

int s21_min(int first, int second) { return first < second ? first : second; }

void s21_add_long_bits_ignore_scale(s21_long_decimal *first,
                                    s21_long_decimal *second,
                                    s21_long_decimal *result) {
  s21_reset_long_only_bits(result);
  int actual_index =
      s21_min(MAX_LONG_INDEX, 1 + s21_max(s21_get_top_long_bit_index(first),
                                          s21_get_top_long_bit_index(second)));

  for (int i = 0, buffer = 0; i <= actual_index; i++) {
    int sum = s21_get_long_bit(first, i) + s21_get_long_bit(second, i) + buffer;

    if (sum == 1 || sum == 3) {
      s21_set_long_bit(result, i);
    }

    buffer = sum < 2 ? 0 : 1;
  }
}

/* where is first >= second */
void s21_sub_long_bits_ignore_scale(s21_long_decimal *first,
                                    s21_long_decimal *second,
                                    s21_long_decimal *result) {
  s21_reset_long_only_bits(result);
  int first_top_bit_index = s21_get_top_long_bit_index(first);

  for (int i = 0, buffer = 0; i <= first_top_bit_index; i++) {
    int difference =
        s21_get_long_bit(first, i) - s21_get_long_bit(second, i) - buffer;

    if (difference == 1 || difference == -1) {
      s21_set_long_bit(result, i);
    }

    buffer = difference >= 0 ? 0 : 1;
  }
}

int s21_integer_div_long_ignore_scale(s21_long_decimal *value,
                                      s21_long_decimal *divider,
                                      s21_long_decimal *result,
                                      s21_long_decimal *remainder) {
  if (s21_is_long_zero(divider)) {
    return NAN_ERROR;
  }

  s21_reset_long_only_bits(result);
  s21_copy_long(value, remainder);

  if (s21_compare_only_long_bits(value, divider) >= 0) {
    int shift =
        s21_get_top_long_bit_index(value) - s21_get_top_long_bit_index(divider);
    s21_long_decimal shifted_divider = INIT_ZERO_S21_LONG_DECIMAL;
    s21_copy_long(divider, &shifted_divider);
    s21_shift_long_bits_to_left(&shifted_divider, shift);

    for (int i = shift; i >= 0; i--) {
      if (s21_compare_only_long_bits(remainder, &shifted_divider) >= 0) {
        s21_long_decimal buffer = INIT_ZERO_S21_LONG_DECIMAL;
        s21_copy_long(remainder, &buffer);
        s21_sub_long_bits_ignore_scale(&buffer, &shifted_divider, remainder);
        s21_set_long_bit(result, i);
      }

      if (i) s21_shift_long_bits_to_right(&shifted_divider, 1);
    }
  }

  return OK;
}